using System;
using System.Collections.Generic;
using System.IO;
using BSDS.Core.Data.TemporaryFiles;
using BSDS.Core.Infrastructure.Logging;
using BSDS.Service.Utils;

namespace BSDS.Service.Logic
{
    public class FileProcessor
    {
        private readonly TempFolderManager tempFolderManager;
        private readonly FilesManager filesManager;
        private readonly CommandExecutor commandExecutor;
        private readonly Logger logger;
        private readonly FileWatcherFactory fileWatcherFactory;
        private readonly bool cleanTempAfterEachCommand;

        private FileSystemWatcherAdapter directoryWatcher;

        public FileProcessor(TempFolderManager tempFolderManager, FilesManager filesManager, CommandExecutor commandExecutor, Logger logger, 
            FileWatcherFactory fileWatcherFactory, bool cleanTempAfterEachCommand)
        {
            this.tempFolderManager = tempFolderManager;
            this.filesManager = filesManager;
            this.commandExecutor = commandExecutor;
            this.logger = logger;
            this.fileWatcherFactory = fileWatcherFactory;
            this.cleanTempAfterEachCommand = cleanTempAfterEachCommand;
        }

        public void Intialize()
        {
            filesManager.Initialize();

            IntializeInputFolderWatcher();
        }

        private void IntializeInputFolderWatcher()
        {
            directoryWatcher = fileWatcherFactory.Create(filesManager.InputDirectory.FullName);
            directoryWatcher.Created += NewFileCreatedHandler;
            directoryWatcher.EnableRaisingEvents = true;
        }

        private void NewFileCreatedHandler(object sender, FileSystemEventArgs e)
        {
            try
            {
                logger.Log("Processing file: " + e.Name);

                var commandParameters = new Dictionary<string, string> {{"@filename", e.FullPath}};

                ProcessingResult result = commandExecutor.Process(commandParameters);

                var outputDirectory = result == ProcessingResult.Success
                                          ? filesManager.SuccessDirectory
                                          : filesManager.FailedDirectory;


                filesManager.MoveFileToFolder(e.FullPath, outputDirectory);
                filesManager.CleanUpFiles();

                if (cleanTempAfterEachCommand)
                {
                    tempFolderManager.CleanUpFiles();
                }
            }
            catch (Exception ex)
            {
                logger.Log("Error processing " + ex.Message);
            }
        }
    }
}